package co.edu.udea.iw.rtf.dao.impl;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import co.edu.udea.iw.rtf.dao.SolicitudDAO;
import co.edu.udea.iw.rtf.dto.Solicitud;
import co.edu.udea.iw.rtf.dto.Sucursal;
import co.edu.udea.iw.rtf.exception.RTFDaoException;

public class SolicitudDAOImpl extends HibernateDaoSupport implements SolicitudDAO {

	/**
	 * Metodo que almacena en el sistema los datos de la solicitud enviada como parametro
	 * Guarga los datos en una Session hibernate y luego realiza el commit para ingresarlos a la base de datos
	 * @param solicitud
	 */
	@Override
	public void guardar(Solicitud solicitud) throws RTFDaoException {
		Session session = null;
		Transaction tx = null;
		try{
			
			session = getSession();
			tx = session.beginTransaction();
			session.save(solicitud);
			tx.commit();
			
		}catch (HibernateException e) {
			throw new RTFDaoException(e);
		}
	}
	
	/**
	 * Metodo que actualiza en la base de datos que la solicitud ya fue asignada
	 * Consulta en la base de datos la solicitud que se envio como parametros
	 * Asigna a la solicitud consultada los datos que se van a modificar
	 * Actualiza los datos por medio de Session Hibernate y realiza el commit en la base de datos
	 * @param solicitu
	 */
	@Override
	public void actualizar(Solicitud solicitud) throws RTFDaoException {
		Session session = null;
		Transaction tx = null;
		Solicitud solicitudGuardada = new Solicitud();
		
		try{
			
			session = getSession();
			tx = session.beginTransaction();
			Integer codigo = solicitud.getCodigo();
			solicitudGuardada = (Solicitud)session.get(Solicitud.class, codigo);
			solicitudGuardada.setAsignada(true);
			solicitudGuardada.setUsuarioAsignada(solicitud.getUsuarioAsignada());
			solicitudGuardada.setFechaAsignacion(solicitud.getFechaAsignacion());
			
			session.update(solicitudGuardada);
			tx.commit();
			
		}catch (HibernateException e) {
			throw new RTFDaoException(e);
		}
	}
	
	/**
	 * Metodo que obtiene los datos de una solicitud de acuerdo al codigo
	 * Crea un objeto de tipo Solicitud al cual asigna los datos obtenidos en el Get y luego lo retorna
	 * @return Solicitud
	 * @param codigo
	 */
	@Override
	public Solicitud obtener(Integer codigo) throws RTFDaoException {
		
		Solicitud solicitud = new Solicitud();
		Session sesion = null;
		try{
			sesion = getSession();
			
			solicitud = (Solicitud)sesion.get(Solicitud.class, codigo);
				
			return solicitud;
		}catch (HibernateException e) {
			throw new RTFDaoException(e);
		}
		
		
	}
	
	/**
	 * Metodo que ontiene la lista de solicitudes asignadas a un usuario
	 * Crea un ArrayList al cual asigna la lista de solicitudes consultadas por medio de Session Hibernate
	 * @return List<Solicitud>
	 * @param login
	 */
	@Override
	public List<Solicitud> obtenerAsignadas(String login) throws RTFDaoException {
		
		List<Solicitud> solicitudes = new ArrayList<Solicitud>();
		Session sesion = null;
		try{
			sesion = getSession();
			solicitudes = sesion.createCriteria(Solicitud.class, login)
			        .add(Restrictions.eq("usuarioAsignada.login", login))
			        .list();	

			return solicitudes;
		}catch (HibernateException e) {
			throw new RTFDaoException(e);
		}
		
			
	}
	
	/**
	 * Metodo que obtiene la lista de solictudes sin responder que tiene asignada un usuario
	 * Crea un ArrayList al cual asigna la lista de solicitudes consultadas por medio de Session Hibernate
	 * @return List<Solicitud>
	 * @param login
	 */
	@Override
	public List<Solicitud> obtenerSinResponder(String login) throws RTFDaoException {
		
		List<Solicitud> solicitudes = new ArrayList<Solicitud>();
		Session sesion = null;
		try{
			sesion = getSession();
			solicitudes = sesion.createCriteria(Solicitud.class, login)
			        .add(Restrictions.eq("usuarioAsignada.login", login))
			        .add(Restrictions.eq("respondida", false))
			        .addOrder(Order.asc("fechaSolicitud"))
			        .list();	
			
			return solicitudes;
		}catch (HibernateException e) {
			throw new RTFDaoException(e);
		}
		
			
	}
	
	/**
	 * Metodo que obtiene la lista de solicitudes pendientes por responder asignadas a una sucursal
	 * Crea un ArrayList al cual asigna la lista de solicitudes consultadas que no han sido respondidas por medio de 
	 * Session Hibernate y que pertenezcan a la sucursal indicada
	 * @return List<Solicitud>
	 * @param sucursal
	 */
	@Override
	public List<Solicitud> obtenerPendientePorSucursal(Sucursal sucursal) throws RTFDaoException {
		
		List<Solicitud> solicitudes = new ArrayList<Solicitud>();
		Session sesion = null;
		try{
			sesion = getSession();
			solicitudes = sesion.createCriteria(Solicitud.class)
			        .add(Restrictions.eq("sucursal", sucursal))
			        .add(Restrictions.eq("respondida", false))
			        .list();	
			
			return solicitudes;
		}catch (HibernateException e) {
			throw new RTFDaoException(e);
		}
		
			
	}
	
	/**
	 * Metodo que obtiene la lista de de solicitudes asignadas a una sucursal
	 * Crea un Array List al cual asigna las solicitudes consultadas que pertenecen a la sucursal y las retorna
	 * @return List<Solicitud>
	 * @param sucursal
	 */
	@Override
	public List<Solicitud> obtenerPorSucursal(Sucursal sucursal) throws RTFDaoException {
		
		List<Solicitud> solicitudes = new ArrayList<Solicitud>();
		Session sesion = null;
		try{
			sesion = getSession();
			solicitudes = sesion.createCriteria(Solicitud.class)
			        .add(Restrictions.eq("sucursal", sucursal))
			        .list();	
			
			return solicitudes;
		}catch (HibernateException e) {
			throw new RTFDaoException(e);
		}
		
			
	}
	
	/**
	 * Metodo que obtiene todas las solicitudesque han sido realizadas
	 * Crea una Array List al cual asigna la lista de solicitudes obtenidas y las ordena de acurdo a la fecha de solicitud
	 * @return List<Solicitud>
	 */
	@Override
	public List<Solicitud> obtener() throws RTFDaoException {
		

		List<Solicitud> solicitudes = new ArrayList<Solicitud>();
		Session sesion = null;
		try{
			sesion = getSession();
			solicitudes = sesion.createCriteria(Solicitud.class)
					.addOrder(Order.asc("fechaSolicitud"))
					.list();     	

			return solicitudes;
		}catch (HibernateException e) {
			throw new RTFDaoException(e);
		}
		
	}

	@Override
	public void actulizarRespuesta(Solicitud solicitud) throws RTFDaoException {
		
		Session session = null;
		Transaction tx = null;
		Solicitud solicitudGuardada = new Solicitud();
		
		try{
			
			session = getSession();
			tx = session.beginTransaction();
			Integer codigo = solicitud.getCodigo();
			solicitudGuardada = (Solicitud)session.get(Solicitud.class, codigo);
			solicitudGuardada.setRespondida(true);
			solicitudGuardada.setUsuarioResponde(solicitud.getUsuarioResponde());
			solicitudGuardada.setFechaRespuesta(solicitud.getFechaRespuesta());
			solicitudGuardada.setTextoRespuesta(solicitud.getTextoRespuesta());
			
			session.update(solicitudGuardada);
			tx.commit();
			
		}catch (HibernateException e) {
			throw new RTFDaoException(e);
		}
	}

	@Override
	public List<Solicitud> obtenerSinAsignar() throws RTFDaoException {
		// TODO Auto-generated method stub
		List<Solicitud> solicitudes = new ArrayList<Solicitud>();
		Session sesion = null;
		try{
			sesion = getSession();
			solicitudes = sesion.createCriteria(Solicitud.class)
					.add(Restrictions.eq("asignada", false))
					.list();     	

			return solicitudes;
		}catch (HibernateException e) {
			throw new RTFDaoException(e);
		}
	}

}
